package com.foreknow.spring;

import com.foreknow.bean.Admin;
import com.foreknow.service.AdminService;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * IOC容器
 */
public class ClassPathXmlApplicationContext implements BeanFactory {
    private Map<String,Object> beans = new HashMap<>();
    public ClassPathXmlApplicationContext() throws JDOMException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        // 1.创建一个SAXBuilder的对象，解析器
        SAXBuilder saxBuilder = new SAXBuilder();
        // 2.构造文档Document对象
        Document document = saxBuilder.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
        // 3.通过document对象获取xml文件的根节点
        Element root = document.getRootElement();
        // 4. 获取根节点下的子节点的List集合
        List<Element> list =  root.getChildren();
        // 5. 遍历list集合获取每一个子节点
        for(int i = 0;i<list.size();i++) {
            Element element = list.get(i);
            //获取到id和class
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");
            //需要将clazz转为对象
            Object o = Class.forName(clazz).newInstance(); //AdminServiceImpl对象
            //将对象添加到Map容器中
            beans.put(id,o);
            //获取到bean中的property
            for (Element propertyElement:element.getChildren()) {
                String name = propertyElement.getAttributeValue("name"); //adminDao
                String bean = propertyElement.getAttributeValue("bean"); //u
                //从map集合中获取到AdminDaoImpl对象
                Object beanObject = beans.get(bean);
                //通过反射动态调用AdminServiceImpl对象中的set方法初始化化接口
                String methodName = "set" + name.substring(0,1).toUpperCase() + name.substring(1); //setAdminDao
                //通过反射获取方法
                Method method = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
                //调用方法 o表示的是AdminServiceImpl对象  beanObject表示AdminDaoImpl对象
                method.invoke(o,beanObject);
            }
        }
    }

    @Override
    public Object getBean(String id) {
        return beans.get(id);
    }

    public static void main(String[] args) {
        try {
            BeanFactory context = new ClassPathXmlApplicationContext();
            //AdminService service = new AdminServiceImpl();
            //service.setAdminDao(new AdminDaoImpl());
            AdminService service = (AdminService) context.getBean("adminService");
            service.add(new Admin());

        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException | ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
